define(['map'], function (map) {

    let cst = {
        animating : false,//是否开始执行，false开始，true暂停
        speed : 500,//默认移动速度
        now : new Date().getTime(),//时间戳

        GeoJsonformat: new ol.format.GeoJSON(),
        currLayer : new ol.layer.Vector({
            source: new ol.source.Vector(),
            zIndex: 154,
        }),//动画实现图层
        hideLayer : null,//隐藏图层
        showLayer : null,//显示图层
        StyleFun: null,// 动画中要素的样式函数

        hideLayerFeatures : [],//隐藏图层要素集合
        showLayerFeatures: [],//显示图层要素集合
        features: [], // 动画数据来源要素集合

        afterAnimateCallBack: null, // 动画结束回调
        isZoomOut: false, // 是否清理隐藏图层
        _isinit: false,
    }
    let olmap = null;
    
    let Animate = function (param) {
        $.extend(cst, param);
        olmap = map.getMap();
        map.addLayer("animate_Layer", cst.currLayer);
        dealBug();
    }

    /**
     * 初始化方法
     * @param hideLayer 需要隐藏的层
     * @param showLayer 需要展示的层
     * @param afterAnimateCallBack 回调方法
     */
    Animate.prototype.init = function(hideLayer, showLayer, afterAnimateCallBack) {
            cst.hideLayer = hideLayer;
            cst.showLayer = showLayer;
            cst.afterAnimateCallBack = afterAnimateCallBack;
            cst.isZoomOut = cst.showLayer.get("direction") === 'in' ? false : true;
            cst.hideLayerFeatures = cst.hideLayer.getSource().getFeatures();
            cst.showLayerFeatures = cst.showLayer.getSource().getFeatures();
            cst.features = cst.isZoomOut ? cst.hideLayerFeatures : cst.showLayerFeatures;
            this.setAnimateDatas();
            cst._isinit = true;
    }

    /**
     * 初始化并启动动画
     * @param hideLayer 需要隐藏的层
     * @param showLayer 需要展示的层
     * @param afterAnimateCallBack 回调方法
     */
    Animate.prototype.initAndStart = function(hideLayer, showLayer, afterAnimateCallBack) {
        this.init(hideLayer, showLayer, afterAnimateCallBack);
        return this.startAnimation();
    }

    /**
     * 启动动画
     */
    Animate.prototype.startAnimation = function() {
        return cst._isinit && startAnimation();
    }

    Animate.prototype.setAnimateDatas = function() {
        cst.isZoomOut ? this.setZoomOutAnimateDatas() : this.setZoomInAnimateDatas()
    }

    /**
     * 设置zoomIn的动画数据
     */
    Animate.prototype.setZoomInAnimateDatas = function () {
        let that = this;
        // fea为父，feature为子
        cst.hideLayerFeatures.forEach(fea => {
            cst.showLayerFeatures.forEach(feature => {
                if (fea.get("id") === feature.get("pid").slice(0, fea.get("id").length)) {
                    feature.set("routeCoords", that.getRouteCoordsByPoints([fea.get("center"), feature.get("center")]));
                }
            });
        })
    }

    /**
     * 设置zoomOut的动画数据
     */
    Animate.prototype.setZoomOutAnimateDatas = function () {
        let that = this;
        // feature为父，fea为子
        cst.showLayerFeatures.forEach(feature => {
            cst.hideLayerFeatures.forEach(fea => {
                if (feature.get("id") === fea.get("pid").slice(0, feature.get("id").length)) {
                    fea.set("routeCoords", that.getRouteCoordsByPoints([fea.get("center"), feature.get("center")]));
                }
            });
        })
    }

    /**
     * 根据起点和终点返回路径点
     * @param {Array} coordinateArr 起点和终点数组：[起点, 终点]
     * @returns 路径点
     */
    Animate.prototype.getRouteCoordsByPoints = function (coordinateArr) {
        let line = turf.lineString(coordinateArr);
        let curved = turf.bezierSpline(line);
        const geoJsonLine = cst.GeoJsonformat.readFeatures(curved);
        return geoJsonLine[0].getGeometry().getCoordinates();
    }

    /**
     * 处理动画首次加载时的图标不显示问题
     */
    function dealBug() {
        let dealInit_layer_source = new ol.source.Vector();
        map.addLayer("dealInit_layer", new ol.layer.Vector({
            style: new ol.style.Style({
                image: new ol.style.Icon({
                    anchor: [0.28, 0.98],
                    crossOrigin: 'anonymous',
                    src: "../../src/source/images/marker.png",
                })
            }),
            source: dealInit_layer_source,
            zIndex: 1,
        }));
        dealInit_layer_source.addFeature(new ol.Feature(new ol.geom.Point([105.66746201038362, 35.862170650959015])));
        setTimeout(() => {
            map.removeLayer("dealInit_layer");
        }, 300);
    }

    /**
     * 动画事件操作
     * @param event
     */
    function moveFeature(event){
        let vectorContext = event.vectorContext;
        let frameState = event.frameState;
        if (cst.animating) {
            // 计算走向点index
            let elapsedTime = frameState.time - cst.now;
            let index = Math.round(cst.speed * elapsedTime / 1000);
            let routeMaxindex = 0;
            cst.features.forEach((fea) => {
                let routeCoords = fea.get("routeCoords");
                if (routeCoords) {
                    routeMaxindex = routeCoords.length - 1;
                    index = index > routeMaxindex ? routeMaxindex : index;
                    let Opacity = index / routeMaxindex;
                    let coordinate = routeCoords[index]
                    let currentPoint = new ol.geom.Point(coordinate);
                    let feature = new ol.Feature(currentPoint);
                    let styleOpacity = cst.isZoomOut ? 1 - Opacity : Opacity;
                    if (index > routeMaxindex * 0.7 && cst.isZoomOut) {
                        styleOpacity = 0;
                    }
                    let style = cst.StyleFun(fea, styleOpacity);
                    cst.hideLayer.setOpacity(1 - Opacity);
                    vectorContext.drawFeature(feature, style);
                    cst.isZoomOut && cst.showLayer.setOpacity(Opacity);
                }
            });
            if (index >= routeMaxindex) {
                stopAnimation();
            }
        }
        olmap.render();
    }

    /**
     * 开始动画
     */
    function startAnimation() {
        if (cst.animating) {
            stopAnimation();
        } else {
            cst.animating = true;
            cst.now = new Date().getTime();
            cst.isZoomOut && cst.hideLayer.getSource().clear();
            cst.currLayer.on('postcompose', moveFeature);
            olmap.render();
        }
    }

    /**
     * 停止动画
     */
    function stopAnimation(){
        cst.animating = false;
        cst.currLayer.un('postcompose', moveFeature);
        // 一定要保证解绑事件在执行回调之前执行
        cst.afterAnimateCallBack && cst.afterAnimateCallBack();
    }
    return Animate;
})